"""
map方法的使用： map（func，* iterables，timeout = None，chunksize = 1 ），返回一个迭代器。与内置函数map（func，* iterables）有点相似，但是有两点不同：

1、立即获取iterables，而不是惰性获取
2、异步执行func，并且支持多次并发调用
从调用 Executor.map() 开始的 timeout 秒之后，如果在迭代器上调用了 __next__() 并且无可用结果的话，迭代器会抛出 concurrent.futures.TimeoutError 异常。timeout 秒数可以是浮点数或者整数，如果设置为 None 或者不指定，则不限制等待时间。

如果 func 调用抛出了异常，那么该异常会在从迭代器获取值的时候抛出。

当使用 ProcessPoolExecutor 的时候，这个方法会把 iterables 划分成多个块，作为独立的任务提交到进程池。这些块的近似大小可以通过给 chunksize 指定一个正整数。对于很长的 iterables，使用较大的 chunksize 而不是采用默认值 1，可以显著提高性能。对于 ThreadPoolExecutor，chunksize 不起作用。

注意： 不管并发任务的执行次序如何，map 总是基于输入顺序来返回值。map 返回的迭代器，在主程序迭代的时候，会等待每一项的响应。

"""
from concurrent.futures import ThreadPoolExecutor
import requests


def thread_run(url):
    try:
        re = requests.get(url=url, timeout=30)
        re.raise_for_status()
        re.encoding = re.apparent_encoding
        return re.text
    except:
        return


if __name__ == "__main__":
    executor = ThreadPoolExecutor(max_workers=2)
    urls = [
        "https://blog.csdn.net/weixin_41599977/article/details/92404112",
        "https://blog.csdn.net/weixin_41599977/article/details/91048654",
        "https://blog.csdn.net/weixin_41599977/article/details/90300773"
    ]
    # 使用map方法，无需提前使用submit方法，map方法与标准库里额map含义相似，
    # 都是将序列中的每个元素都执行同一个函数。下面的代码就是对urls中的每个元
    # 素都执行thread_run函数，并分配到线程池中。
    for url, data in zip(urls, executor.map(thread_run, urls)):
        print("In the main thread: get page {} success, {} bytes".format(url, len(data)))
